#include "android_service/android_message.h"

using namespace std;


char *MESSAGE_TYPES[] = {
    //Needed to support the way Java handles Enumeration type - 
    "ANDROID_UNDEFINED",
    "ANDROID_INTRO",  // Just a welcom aboad message
    "ANDROID_SUCCESS", 
    "ANDROID_BROADCAST",  // one way voice message - 
    "ANDROID_QUESTION", // Question with replay - 
    "ANDROID_GRID_LOCATION", // Ask human for a desired map location - 
    "ANDROID_BIOMETRICS", // ask Android to generate biometric signature 
    "ANDROID_USER_LIMIT"
};
    
int MESSAGE_VARS[] = {
    //Needed to support the way Java handles Enumeration type - 
    ANDROID_UNDEFINED,
    ANDROID_INTRO, // Just a welcom aboad message
    ANDROID_SUCCESS, 
    ANDROID_BROADCAST,  // one way voice message - 
    ANDROID_QUESTION,   // Question with replay - 
    ANDROID_GRID_LOCATION, // Ask human for a desired map location - 
    ANDROID_BIOMETRICS,// ask Android to generate biometric signature 
    ANDROID_USER_LIMIT 
};


///
/// Field tokenizer for individual message
void parse_list(const string list_str, vector<string>& recv, const char sep,
                size_t start) {
    size_t pos;
    pos = list_str.find(sep, start);

    while(pos != string::npos) {
        recv.push_back(list_str.substr(start, (pos - start)));
        start = pos + 1;
        pos = list_str.find(sep, start);
    }

    //pos == str::npos means that we take the final substring
    recv.push_back(list_str.substr(start));
}

//---- Message ----
Message::Message() : separator(':'), MsgPriority(0) { 
    initMsgTable();
}
Message::Message(int type) : separator(':'), MsgType(type), MsgPriority(0) { 
    initMsgTable();
}

void Message::initMsgTable() {
    //Needed to support the way Java handles Enumeration type - 
    int max = sizeof(MESSAGE_VARS) / sizeof(MESSAGE_VARS[0]);
    for(int i = 0; i < max; i++) {
        str2int_map.insert(make_pair<string,int>(MESSAGE_TYPES[i], MESSAGE_VARS[i]));
        int2str_map.insert(make_pair<int,string>(MESSAGE_VARS[i], MESSAGE_TYPES[i]));
    }
}

Message::~Message() {
    int2str_map.clear();
    str2int_map.clear();
}
void Message::reset() {
    parts.clear();
    MsgType = ANDROID_UNDEFINED;
}
int Message::read(string message, bool fromAndroid) {
    size_t pos;
    pos = message.find(separator);
    if(pos == string::npos) {
        cout << "Err: Unable to parse message - malformed header -1" << endl;
        return -1;
    }
    string msg_type = message.substr(0, pos);
    if(fromAndroid) {
        map<string,int>::iterator it = str2int_map.find(msg_type);
        if(it == str2int_map.end()) {
            cout << "Err: Unable to parse message - malformed header -2" << endl;
            return -1;
        }
        MsgType = it->second;
    } else {
        map<int, string>::iterator it = 
            int2str_map.find(atoi(msg_type.c_str()));
        if(it == int2str_map.end()) {
            cout << "Err: Unable to parse message - malformed header -3" << endl;
            return -1;
        }
        MsgType = it->first;
    }
    
    //MsgType = atoi(message.substr(0, pos).c_str());
    if(MsgType == ANDROID_UNDEFINED) {
        cout << "Err: Unable to parse message - malformed header -4" << endl;
        return -1;
    }
    
    // get remaining message elements
    parse_list(message, parts, separator, pos + 1);

    return 0;
}

int Message::size() const {
    return parts.size();
}

string Message::entry(unsigned int index) const {
    if(index < parts.size()) {
        return parts[index];
    }
    return "";
}

int Message::message_type() const {
    return MsgType;
}
int Message::message_priority() const {
    return MsgPriority;
}

void Message::message_type(int t) {
    MsgType = t;
    if(t == ANDROID_BIOMETRICS) {
	MsgPriority = 100;
    }
}

void Message::add_entry(string entry) {
    parts.push_back(entry);
}
void Message::insert_entry(int i, string entry) {
    parts.insert(parts.begin()+i,entry);
}

string Message::android_str() const {
    ostringstream message;
    map<int, string>::const_iterator it = 
            int2str_map.find(MsgType);
        
    if(it == int2str_map.end()) {
        cout << "Err: Unable to parse message - malformed header -2" << endl;
        return "";
    }
    message << it->second;
    vector<string>::const_iterator e;
    for(e = parts.begin(); e != parts.end(); e++) {
        message << separator << *e;
    }
	//message << "#";

    return message.str();
}

string Message::str() const {
    ostringstream message;
    message << MsgType;

    vector<string>::const_iterator e;
    for(e = parts.begin(); e != parts.end(); e++) {
        message << separator << *e;
    }
	//message << "#";

    return message.str();
}
string Message::str(int start_pos) const {
    if(this->size() <= start_pos) return "";
    ostringstream message;
    vector<string>::const_iterator e;
    for(e = parts.begin()+start_pos; e != parts.end(); e++) {
        message << separator << *e;
    }

    return message.str();
}

Message& Message::operator=(Message& msg) {
    this->reset();
    this->MsgType = msg.MsgType;
    for(int i = 0; i < msg.size(); i++) {
        this->add_entry(msg.entry(i));
    }
    return *this;
}
//Overload the < operator.
bool Message::operator< (const Message& msg)
{
        return this->MsgPriority > msg.MsgPriority;
}
//Overload the < operator.
bool Message::operator> (const Message& msg)
{
        return this->MsgPriority < msg.MsgPriority;
}

